/**
 * Copyright (C) 2012 The SkyTvOS Project
 * <p/>
 * Version     Date           Author
 * ─────────────────────────────────────
 * 2012-9-19         rico
 */

package com.tianci.appstore.utils;

import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.util.Log;
import android.util.LruCache;

import com.coocaa.x.framework.utils.LogUtils;
import com.skyworth.framework.skysdk.properties.SkyGeneralProperties;
import com.skyworth.framework.skysdk.util.MD5;
import com.tianci.appstore.database.AppStoreDB;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.lang.ref.SoftReference;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;

/**
 * @author rico
 * @version TODO (write something)
 * @ClassName SkyNetImageCache
 * @Description TODO (write something)
 * @date 2012-9-19
 */
public class SkyNetImageCache implements SkyNetImageListener {
    static public interface ImageLoadListener {
        public void loadFinished(String url, Bitmap result);
    }

    private static final int SOFT_CACHE_CAPACITY = 40;
    private static LinkedHashMap<String, SoftReference<Bitmap>> sSoftBitmapCache = new LinkedHashMap<String, SoftReference<Bitmap>>(SOFT_CACHE_CAPACITY, 0.75f, true);

    private static final int hardCachedSize = 10 * 1024 * 1024;
    private static HashMap<String, String> mLogoMap = new HashMap<String, String>();
    private static int decodemaxSize = -1;
    private static String mCachePath = "";
    private static LruCache<String, Bitmap> sHardBitmapCache = new LruCache<String, Bitmap>(hardCachedSize) {
        @Override
        public int sizeOf(String key, Bitmap value) {
            return value.getRowBytes() * value.getHeight();
        }

        @Override
        protected void entryRemoved(boolean evicted, String key,
                                    Bitmap oldValue, Bitmap newValue) {
            LogUtils.d("HOMEPAGE", "hard cache is full , push to soft cache");
            // 硬引用缓存区满，将一个最不经常使用的oldvalue推入到软引用缓存区
            sSoftBitmapCache.put(key, new SoftReference<Bitmap>(oldValue));
        }
    };

    // 放图片如缓存中
    private boolean putBitmap(String key, Bitmap bitmap) {
        if (bitmap != null) {
            sHardBitmapCache.put(key, bitmap);
            return true;
        }
        return false;
    }


    public Bitmap getBitmap(String imageurl) {
        //String key = Base64.encodeToString(imageurl.getBytes());
        if (imageurl == null) {
            return null;
        }
        return getBitmapEx(imageurl);
    }

    // 从缓存中获取bitmap
    private Bitmap getBitmapEx(String key) {
        synchronized (sHardBitmapCache) {
            final Bitmap bitmap = sHardBitmapCache.get(key);
            if (bitmap != null)
                return bitmap;
        }
        // 硬引用缓存区间中读取失败，从软引用缓存区间读取
        return null;
    }

    private SkyFixedThreadPool threadPool, appListThreadPool;

    private static SkyNetImageCache imageCache = new SkyNetImageCache();

    public SkyNetImageCache() {
        threadPool = new SkyFixedThreadPool(1, false);
        appListThreadPool = new SkyFixedThreadPool(5, true);
        imageCache = this;

        String decodeSize = SkyGeneralProperties.getProperty("BITMAP_DECODE_MAX_SIZE");
        if (decodeSize != null) {
            decodemaxSize = Integer.valueOf(decodeSize);
        }

    }

    public static void setCachePath(String path) {
        if (path != null || !path.equals("")) {
            File file = new File(path);
            if (!file.isDirectory() || !file.exists())
                throw new RuntimeException("cache dir is not exist");
            mCachePath = path;
        } else {
            throw new RuntimeException("cache dir can not be null");
        }
        File file = new File(mCachePath);
        String[] logos = file.list();
        if (logos != null && logos.length > 0) {
            for (String string : logos) {
                String[] pnameUrl = string.split("_");
                mLogoMap.put(pnameUrl[0], pnameUrl[1]);
            }
        }
    }

    public static SkyNetImageCache getSkyNetImageCache() {
        return imageCache;
    }

//	public boolean downloadCornerIcon1(String url,ImageLoadListener mListener){
//		String CornerIcon = MD5.md5s(url);
//		LogUtils.d("liqiwen", "downloadUrl---id:"+CornerIcon);
//		return downloadUrl(CornerIcon, url, mListener);
//	}

    //下载主页的logo
    public boolean downloadUrl(String pkg, String url, ImageLoadListener mListener, int width, int height) {
//		LogUtils.d("liqiwen", "downloadUrl---pkg:"+pkg+" "+url);
        return downloadUrl(pkg, url, mListener, width, height, 0);
    }

    public boolean downloadUrl(String pkg, String url, ImageLoadListener mListener, int width, int height, int corner) {
//		LogUtils.d("liqiwen", "downloadUrl---pkg:"+pkg+" "+url);
        String picurl = MD5.md5s(url);
        Bitmap bm = getBitmap(picurl);
        if (bm != null) {
            mListener.loadFinished(url, bm);
            return true;     //需要显示默认背景图片
        }
        threadPool.execute(new ImageHttpLoader(pkg, url, mListener, width, height, corner));
        return false;
    }


    public void downloadSreenShot(boolean needSave, String url, ImageLoadListener mListener) {
        LogUtils.d("shot", "downloadSreenShort---url:" + url);
        threadPool.execute(new ScreenshotLoader(needSave, url, mListener));
    }

    //下载列表logo
    public boolean downloadAppListLogo(String pkg, String url, ImageLoadListener mListener, int width, int height,int corner) {
//		LogUtils.d("liqiwen", "downloadAppListLogo---id:"+pkg+" "+url);
        String iconurl = MD5.md5s(url);
        Bitmap bm = getBitmap(iconurl);
        if (bm != null) {
            mListener.loadFinished(url, bm);
            return true;     //需要显示默认背景图片
        }
        appListThreadPool.execute(new ImageHttpLoader(pkg, url, mListener, width, height, corner));
        return false;
    }
    public boolean getLogoByPkg(final String pkg, final ImageLoadListener mListener, int width, int height) {
        return getLogoByPkg(pkg,mListener,width,height,0);
    }

    public boolean getLogoByPkg(final String pkg, final ImageLoadListener mListener, int width, int height,int corner) {
//        AsyncTask.runOnThread(new Runnable()
//        {
//            @Override
//            public void run()
//            {
        // TODO Auto-generated method stub
        List<String> pathList = AppStoreDB.getInstance().getPathByPkg(pkg);
        LogUtils.d("aa", "getLogoByPkg---size:" + pathList.size());
        if (pathList != null && pathList.size() >= 1) {
//                    int index = pathList.size()-1;
            final String path = pathList.get(0);
            if (!path.equals("")) {
                LogUtils.d("aa", "getLogoByPkg---path:" + path + " " + pkg);
//                        File file = new File(path);
//                        if (file.exists())
//                        {
//                            AsyncTask.runOnThread(new Runnable()
//                            {
//
//                                @Override
//                                public void run()
//                                {
                // TODO Auto-generated method stub
                Bitmap bm = ImageUtils.decodeSampledBitmapFromFile(path, width, height);
                if (bm != null) {
                    if (corner > 0) {
                        try {
                            bm = ImageUtils.getRoundedCornerBitmap(bm, corner);
                        } catch (Exception e) {

                        }
                    }
                    mListener.loadFinished(pkg, bm); // 没有url怎么办？
                }
//                                }
//                            });
//                        }
                return true;
            }
        }
        return false;
//            }
//        });
    }

    @Override
    public void onFinished(String url, String path) {
        // TODO Auto-generated method stub

    }

    @Override
    public void onFailed(String url, String error) {
        // TODO Auto-generated method stub

    }

    @Override
    public void onStreamFinished(String url, Bitmap bitmap) {
        // TODO Auto-generated method stub

    }

    @Override
    public void onStreamFailed(String url) {
        // TODO Auto-generated method stub

    }

    /*
     * 得到图片字节流 数组大小
     * */
    public static byte[] readStream(InputStream inStream) throws Exception {
        ByteArrayOutputStream outStream = new ByteArrayOutputStream();
        byte[] buffer = new byte[1024];
        int len = 0;
        while ((len = inStream.read(buffer)) != -1) {
            outStream.write(buffer, 0, len);
        }
        outStream.close();
        inStream.close();
        return outStream.toByteArray();
    }

    public class ImageHttpLoader extends SkyRunnable {

        private String murl;
        private ImageLoadListener mListener = null;
        private String name = "";
        private String pkg = "";
        private int mWidth = 0;
        private int mHeight = 0;
        private int mCorner = 0;

        ImageHttpLoader(String pkg, String url, ImageLoadListener listener, int width, int height, int corner) {
            murl = url;
            mListener = listener;
            this.pkg = pkg;
            this.name = MD5.md5s(url);
            this.mWidth = width;
            this.mHeight = height;
            this.mCorner = corner;
        }

        public void reloadImage(String downloadUrl, String savePath) throws Exception {
            URL url = new URL(downloadUrl);
            HttpURLConnection conn = (HttpURLConnection) url.openConnection();
            conn.setConnectTimeout(5 * 1000);
            conn.setRequestMethod("GET");
            InputStream inStream = conn.getInputStream();
            if (conn.getResponseCode() == HttpURLConnection.HTTP_OK) {
                BitmapFactory.Options options = new BitmapFactory.Options();
                options.inJustDecodeBounds = true;
                BitmapFactory.decodeStream(inStream, null, options);
                if (isBitmapOutOfSize(options.outHeight * options.outWidth)) {
                    conn.disconnect();
                    return;
                }
                conn.disconnect();
                HttpURLConnection reconn = (HttpURLConnection) url.openConnection();
                reconn.setConnectTimeout(5 * 1000);
                reconn.setRequestMethod("GET");

                InputStream reinStream = null;
                if (reconn.getResponseCode() == HttpURLConnection.HTTP_OK) {
                    reinStream = reconn.getInputStream();
                    if (reinStream != null) {
                        //下载图片
                        byte[] bs = new byte[1024];
                        // 读取到的数据长度
                        int len;
                        // 输出的文件流
                        OutputStream os = new FileOutputStream(savePath);
                        // 开始读取
                        while ((len = reinStream.read(bs)) != -1) {
                            os.write(bs, 0, len);
                        }
                        // 完毕，关闭所有链接
                        os.flush();
                        os.close();
                        reinStream.close();
                    }
                }
            }
            return;
        }

        @Override
        public String call() throws Exception {
            // TODO Auto-generated method stub
            try {
                String basePath = AppStoreDB.getInstance().getIconPath();
                String path = basePath + name;
                Bitmap bitmap = getBitmap(path);
                LogUtils.d("aaaa", "call---(bitmap==null)--path--" + (bitmap == null) + " " + path);
                if (bitmap == null) {
                    LogUtils.d("liqiwen", "need download picture!!!!!!!----");
                    reloadImage(murl, path);
                    bitmap = getBitmap(path);
                    putBitmap(name, bitmap);
//                	LogUtils.d("liqiwen", "call----(bitmap == null):"+(bitmap == null));
                    if (mListener != null) {
                        //存入数据表，供我的查询
                        LogUtils.d("aaaa", "insert db --11-pkg:" + pkg + " path:" + path);
                        if (!pkg.equals(""))
                            AppStoreDB.getInstance().addAppLogoPath(pkg, path, "");
                        mListener.loadFinished(murl, bitmap);
                    }
                } else {
                    putBitmap(name, bitmap);
                    if (mListener != null) {
                        //存入数据表，供我的查询
                        LogUtils.d("aaaa", "insert db --22-pkg:" + pkg + " path:" + path);
                        if (!pkg.equals(""))
                            AppStoreDB.getInstance().addAppLogoPath(pkg, path, "");
                        mListener.loadFinished(murl, bitmap);
                    }
                }

            } catch (FileNotFoundException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
                System.out.println("SDK  filenotfoundexceipton++++++++++++++++++++++++++++++++++++++++++");

                if (mListener != null) {
                    System.out.println("SDK  filenotfoundexceipton1111++++++++++++++++++++++++++++++++++++++++++");
                    mListener.loadFinished(murl, null);
                }
            } catch (OutOfMemoryError e) {
                // TODO: handle exception
                if (mListener != null) {
                    System.out.println("SDK  OutOfMemoryError++++++++++++++++++++++++++++++++++++++++++");

                    mListener.loadFinished(murl, null);
                }
            } catch (Exception e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
                System.out.println("SDK  Exception++++++++++++++++++++++++++++++++++++++++++");

                if (mListener != null) {
                    System.out.println("SDK  Exception++++++++++++++++++++++++++++++++++++++++++");

                    mListener.loadFinished(murl, null);
                }
            }
            System.out.println("SDK  call()++++++++++++++++++++++++++++++++++++++++++");

            return murl;
        }


        private Bitmap getBitmap(String path) {
            File file = new File(path);
            if (file.exists()) {
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                Bitmap bitmap = ImageUtils.decodeSampledBitmapFromFile(path, mWidth, mHeight);
                if (mWidth != 0 && mHeight != 0 && bitmap.getWidth() > mWidth) {
                    bitmap = ImageUtils.scale(bitmap, mWidth, mHeight);
                }
                if (mCorner > 0) {
                    try {
                        bitmap = ImageUtils.getRoundedCornerBitmap(bitmap, mCorner);
                    } catch (Exception e) {

                    }
                }
                return bitmap;
            }
            return null;
        }

        @Override
        public String getRunnableId() {
            // TODO Auto-generated method stub
            return murl;
        }
    }

    public class ScreenshotLoader extends SkyRunnable {
        private String murl;
        private ImageLoadListener mListener = null;
        private boolean needSaved = false;
        private String savePath = "";

        ScreenshotLoader(boolean needSave, String url, ImageLoadListener listener) {
            murl = url;
            mListener = listener;
            needSaved = needSave;
            savePath = AppStoreDB.getInstance().getBigScreenPath() + MD5.md5s(murl);
        }

        public void getImage(String downloadUrl) throws Exception {
            URL url = new URL(downloadUrl);
            HttpURLConnection conn = (HttpURLConnection) url.openConnection();
            conn.setConnectTimeout(5 * 1000);
            conn.setRequestMethod("GET");
            InputStream inStream = conn.getInputStream();
            if (conn.getResponseCode() == HttpURLConnection.HTTP_OK) {
                BitmapFactory.Options options = new BitmapFactory.Options();
                options.inJustDecodeBounds = true;
                BitmapFactory.decodeStream(inStream, null, options);
                if (isBitmapOutOfSize(options.outHeight * options.outWidth)) {
                    conn.disconnect();
                    return;
                }
                conn.disconnect();
                HttpURLConnection reconn = (HttpURLConnection) url.openConnection();
                reconn.setConnectTimeout(5 * 1000);
                reconn.setRequestMethod("GET");

                InputStream reinStream = null;
                if (reconn.getResponseCode() == HttpURLConnection.HTTP_OK) {
                    reinStream = reconn.getInputStream();
                    if (reinStream != null) {

                        // 直接获取bitmap
                        if (needSaved) {
                            // 下载图片
                            byte[] bs = new byte[1024];
                            // 读取到的数据长度
                            int len;
                            // 输出的文件流
                            OutputStream os = new FileOutputStream(savePath);
                            // 开始读取
                            while ((len = reinStream.read(bs)) != -1) {
                                os.write(bs, 0, len);
                            }
                            // 完毕，关闭所有链接
                            os.flush();
                            os.close();
                            reinStream.close();
                        } else {
                            Bitmap bitmap = BitmapFactory.decodeStream(reinStream);
                            if (bitmap != null && mListener != null) {
//			                    LogUtils.d("shot", "call----333 path:"+savePath);
                                mListener.loadFinished(murl, bitmap);
                            }
                            reinStream.close();
                        }
                    }
                }
            }
        }

        @Override
        public String call() throws Exception {
            // TODO Auto-generated method stub
            Bitmap bitmap = null;
            if (needSaved) {
                bitmap = getBitmap(savePath);
            }
            LogUtils.d("shot", "(bitmap == null):" + (bitmap == null));
            if (bitmap == null) {
                getImage(murl);
                if (needSaved) {
                    bitmap = getBitmap(savePath);
                    if (bitmap != null && mListener != null) {
//                        LogUtils.d("shot", "call----11111 path:" + savePath);
                        mListener.loadFinished(murl, bitmap);
                    }
                }

            } else {
                if (mListener != null) {
//                    LogUtils.d("shot", "call----22222");
                    mListener.loadFinished(murl, bitmap);
                }
            }
            return murl;
        }

        private Bitmap getBitmap(String path) {
            File file = new File(path);
            if (file.exists()) {
                Bitmap mBitmap = BitmapFactory.decodeFile(path);
                LogUtils.d("shot", "getBitmap !! path:" + savePath + " " + (mBitmap == null));
                return mBitmap;
            }
            return null;
        }

        @Override
        public String getRunnableId() {
            // TODO Auto-generated method stub
            return murl;
        }
    }

    private boolean isBitmapOutOfSize(int cursize) {
        int getsize = cursize;
        if (decodemaxSize > 0) {
            if (getsize >= decodemaxSize) {
                return true;
            }
        } else {
            if (getsize >= 25000000) {
                return true;
            }
        }
        return false;
    }
}
